/**
 * 云层、天空盒子、雨景、雪景
 */

class CesiumBox {
  viewer: any;
  defaultSkyBox: any;
  currentSkyBox: any;
  sunSkyBox: any;
  blueSkyBox: any;
  lastStage: any;

  constructor(viewer: any) {
    this.viewer = viewer;
  }
  /**
   * 初始化云层
   * 会遮挡天地图的三维地面
   */
  initCloudBox() {
    const cloudBox = new Cesium.CloudBox({
      url: "http://support.supermap.com.cn:8090/webgl/examples/webgl/images/clouds-supermap-sm.png",
    });
    // 开启云层
    this.viewer.scene.cloudBox = cloudBox;
    // 默认高亮云层纹理1
    this.viewer.scene.cloudBox.url =
      "http://support.supermap.com.cn:8090/webgl/examples/webgl/images/clouds-supermap-sm.png";

    // 修改
    // this.viewer.scene.cloudBox.url = 'xxx'
  }

  /**
   * 初始化创建天空盒
   * (存在问题)
   */
  initCreateSkyBoxHandler() {
    // 蓝天
    this.sunSkyBox = new Cesium.SkyBox({
      sources: {
        positiveX:
          "http://support.supermap.com.cn:8090/webgl/examples/webgl/images/SkyBox/sunsetglow/Right.jpg",
        negativeX:
          "http://support.supermap.com.cn:8090/webgl/examples/webgl/images/SkyBox/sunsetglow/Left.jpg",
        positiveY:
          "http://support.supermap.com.cn:8090/webgl/examples/webgl/images/SkyBox/sunsetglow/Front.jpg",
        negativeY:
          "http://support.supermap.com.cn:8090/webgl/examples/webgl/images/SkyBox/sunsetglow/Back.jpg",
        positiveZ:
          "http://support.supermap.com.cn:8090/webgl/examples/webgl/images/SkyBox/sunsetglow/Up.jpg",
        negativeZ:
          "http://support.supermap.com.cn:8090/webgl/examples/webgl/images/SkyBox/sunsetglow/Down.jpg",
      },
    });
    // 晚霞
    this.blueSkyBox = new Cesium.SkyBox({
      sources: {
        positiveX:
          "http://support.supermap.com.cn:8090/webgl/examples/webgl/images/SkyBox/bluesky/Right.jpg",
        negativeX:
          "http://support.supermap.com.cn:8090/webgl/examples/webgl/images/SkyBox/bluesky/Left.jpg",
        positiveY:
          "http://support.supermap.com.cn:8090/webgl/examples/webgl/images/SkyBox/bluesky/Front.jpg",
        negativeY:
          "http://support.supermap.com.cn:8090/webgl/examples/webgl/images/SkyBox/bluesky/Back.jpg",
        positiveZ:
          "http://support.supermap.com.cn:8090/webgl/examples/webgl/images/SkyBox/bluesky/Up.jpg",
        negativeZ:
          "http://support.supermap.com.cn:8090/webgl/examples/webgl/images/SkyBox/bluesky/Down.jpg",
      },
    });

    this.defaultSkyBox = this.viewer.scene.skyBox;

    const initialSkyBox = () => {
      if (this.viewer.scene.frameState.passes.render) {
        this.sunSkyBox.update(this.viewer.scene.frameState, true);
        this.blueSkyBox.update(this.viewer.scene.frameState, true);
        this.viewer.scene.postRender.removeEventListener(initialSkyBox);
      }
    };
    this.viewer.scene.postRender.addEventListener(initialSkyBox);

    // 开启天空盒默认晚霞
    this.sunSkyBox.WSpeed = 0.5;
    this.sunSkyBox.show = true;
    this.currentSkyBox = this.sunSkyBox;
    this.viewer.scene.skyBox = this.currentSkyBox;
    this.gradualChange();
    this.blueSkyBox.show = false;
  }

  /**
   * 相机上升到一定位置,天空盒出现渐变效果
   */
  gradualChange() {
    const skyListener = () => {
      var cameraHeight = this.viewer.scene.camera.positionCartographic.height;

      var skyAtmosphereH1 = 22e4; // 大气开始渐变的最大高度
      var skyBoxH1 = 15e4; // 天空开始渐变的最大高度
      var skyBoxH2 = 12e4; // 天空开始渐变的最小高度
      var bufferHeight = 1e4;
      if (
        cameraHeight < skyAtmosphereH1 &&
        Cesium.defined(this.currentSkyBox)
      ) {
        var skyAtmosphereT =
          (cameraHeight - skyBoxH2) / (skyAtmosphereH1 - skyBoxH2);
        if (skyAtmosphereT > 1.0) {
          skyAtmosphereT = 1.0;
        } else if (skyAtmosphereT < 0.0) {
          skyAtmosphereT = 0.0;
        }
        var skyBoxT = (cameraHeight - skyBoxH2) / (skyBoxH1 - skyBoxH2);
        if (skyBoxT > 1.0) {
          skyBoxT = 1.0;
        } else if (skyBoxT < 0.0) {
          skyBoxT = 0.0;
        }
        this.currentSkyBox.alpha = 1.0 - skyBoxT;
        if (cameraHeight > skyBoxH2) {
          this.viewer.scene.skyAtmosphere.show = true;
          this.viewer.scene.skyAtmosphere.alpha = skyAtmosphereT;
          this.viewer.scene.skyBox = this.currentSkyBox;
        } else {
          this.viewer.scene.skyAtmosphere.show = false;
        }
      } else {
        this.viewer.scene.skyAtmosphere.alpha = 1.0;
        this.viewer.scene.skyBox = this.defaultSkyBox;
      }

      //控制相机 速率
      if (this.viewer.scene.skyBox !== this.defaultSkyBox) {
        if (
          cameraHeight > skyBoxH2 - 2 * bufferHeight &&
          cameraHeight < skyBoxH1 + 3 * bufferHeight
        ) {
          this.viewer.scene.screenSpaceCameraController.zoomFactor = 0.4;
        } else {
          this.viewer.scene.screenSpaceCameraController.zoomFactor = 5.0;
        }
      } else {
        this.viewer.scene.skyBox.alpha = 1.0;
        this.viewer.scene.skyAtmosphere.alpha = 1.0;
        this.viewer.scene.screenSpaceCameraController.zoomFactor = 5.0;
      }
    };
    this.viewer.scene.postRender.addEventListener(skyListener);
  }
  changeSkyBox() {
    if (this.sunSkyBox.show == true) {
      this.blueSkyBox.WSpeed = 0.5;
      this.blueSkyBox.show = true;
      this.currentSkyBox = this.blueSkyBox;
      this.viewer.scene.skyBox = this.currentSkyBox;
      this.sunSkyBox.show = false;
    } else {
      this.sunSkyBox.WSpeed = 0.5;
      this.sunSkyBox.show = true;
      this.currentSkyBox = this.sunSkyBox;
      this.viewer.scene.skyBox = this.currentSkyBox;
      this.blueSkyBox.show = false;
    }
  }

  /**
   *  下雨
   */
  initRain() {
    const FS_Rain =
      "uniform sampler2D colorTexture;\n\
				varying vec2 v_textureCoordinates;\n\
			\n\
				float hash(float x){\n\
					return fract(sin(x*133.3)*13.13);\n\
			}\n\
			\n\
			void main(void){\n\
			\n\
				float time = czm_frameNumber / 60.0;\n\
			vec2 resolution = czm_viewport.zw;\n\
			\n\
			vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);\n\
			vec3 c=vec3(.6,.7,.8);\n\
			\n\
			float a=-.4;\n\
			float si=sin(a),co=cos(a);\n\
			uv*=mat2(co,-si,si,co);\n\
			uv*=length(uv+vec2(0,4.9))*.3+1.;\n\
			\n\
			float v=1.-sin(hash(floor(uv.x*100.))*2.);\n\
			float b=clamp(abs(sin(20.*time*v+uv.y*(5./(2.+v))))-.95,0.,1.)*20.;\n\
			c*=v*b; \n\
			\n\
			gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(c,1), 0.5);  \n\
			}\n\
    ";
    var rain = new Cesium.PostProcessStage({
      name: "hi_rain",
      fragmentShader: FS_Rain,
    });
    this.viewer.scene.postProcessStages.add(rain);
    this.lastStage = rain;
  }

  /**
   * 下雪
   */
  initSnow() {
    const FS_Snow =
      "uniform sampler2D colorTexture;\n\
      varying vec2 v_textureCoordinates;\n\
        \n\
      float snow(vec2 uv,float scale)\n\
      {\n\
          float time = czm_frameNumber / 60.0;\n\
          float w=smoothstep(1.,0.,-uv.y*(scale/10.));if(w<.1)return 0.;\n\
          uv+=time/scale;uv.y+=time*2./scale;uv.x+=sin(uv.y+time*.5)/scale;\n\
          uv*=scale;vec2 s=floor(uv),f=fract(uv),p;float k=3.,d;\n\
          p=.5+.35*sin(11.*fract(sin((s+p+scale)*mat2(7,3,6,5))*5.))-f;d=length(p);k=min(d,k);\n\
          k=smoothstep(0.,k,sin(f.x+f.y)*0.01);\n\
          return k*w;\n\
      }\n\
      \n\
      void main(void){\n\
          vec2 resolution = czm_viewport.zw;\n\
          vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);\n\
          vec3 finalColor=vec3(0);\n\
          float c = 0.0;\n\
          c+=snow(uv,30.)*.0;\n\
          c+=snow(uv,20.)*.0;\n\
          c+=snow(uv,15.)*.0;\n\
          c+=snow(uv,10.);\n\
          c+=snow(uv,8.);\n\
      c+=snow(uv,6.);\n\
          c+=snow(uv,5.);\n\
          finalColor=(vec3(c)); \n\
          gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(finalColor,1), 0.5); \n\
    \n\
    }\n\
    ";
    var snow = new Cesium.PostProcessStage({
      name: 'hi_snow',
      fragmentShader: FS_Snow
    });
      this.viewer.scene.postProcessStages.add(snow);
      this.lastStage=snow
  }
  removeSnowOrRain() {
    this.lastStage && this.viewer.scene.postProcessStages.remove(this.lastStage), this.lastStage = null;
  }
}

export default CesiumBox;
